package com.jm.web;

import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.TreeMap;
import java.util.Vector;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.jsp.JspWriter;
import javax.servlet.jsp.PageContext;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import com.jm.report.action.ReportExportActionHelper;
import com.jm.utils.PageJsGear;
import com.jm.utils.StringBuilderEx;
import com.jm.utils.StringHelper;
import com.jm.utils.Token;
import com.jm.utils.Utils;
import com.jm.web.action.BaseAction;
import com.jm.web.action.BaseExportActionHelper;
import com.jm.web.data.BaseDataEntity;
import com.jm.web.data.CrudDataEntity;
import com.jm.web.data.JMForm;
import com.jm.web.data.ReturnData;
import com.jm.web.form.Export;
import com.jm.web.form.Input;
import com.jm.web.form.PageTitle;
import com.jm.web.form.TableToolbar;
import com.jm.web.form.Toolbar;
import com.jm.web.form.support.FormItem;
import com.jm.web.tags.DialogTag;
import com.jm.wf.data.WFInstance;
import com.jm.wf.data.WFOpStep;
import com.jm.wf.data.WFStep;
import com.jm.wf.data.WorkFlow;

/**
 * @author yanjie
 *
 * 2011/09/17 8:34:37 AM
 */
public class BasePage {
	protected Log log = LogFactory.getLog(BasePage.class);
	public final static String TAG_ACCESSDENY_PAGE = "/include/accessdeny.jsp"; //記錄當前頁面
	public final static String TAG_CURRENT_PAGE = "CURRENT.PAGE"; //記錄當前頁面
	public final static String TAG_CURRENT_UTILS = "CURRENT.UTILS"; //記錄當前頁面
	
	public final static String TAG_LAYOUT_NORMAL 	= "normal";
	public final static String TAG_LAYOUT_BORDER 	= "border";
	
	public final static String TAG_ACTION = "action"; 
	public final static String TAG_ACTION_TYPE = "actionType"; 
	public final static String TAG_ACTION_VALUE = "actionValue"; 
	
	public final static int SCRIPTRUN_REALTIME 	= 1;//页面初始化之前
	public final static int SCRIPTRUN_TABS 	= 2;//tabs
	public final static int SCRIPTRUN_VALIDATOR = 3;//验证
	public final static int SCRIPTRUN_CONFIG 	= 4;//config 布局相碰JS
	public final static int SCRIPTRUN_FUNCTION 	= 5;//定义JS function
	public final static int SCRIPTRUN_ONREADY 	= 6;//onready
	public final static int SCRIPTRUN_HTML 	= 7;//html
	public final static int SCRIPTRUN_GRIDDATA 	= 8;//html
	public final static int SCRIPTRUN_LAST 	= 9;//html
	
	protected boolean bInit = false;
	protected boolean bFinshed = false ; //記錄頁請求是否完成
	protected String strDefaultFormID = "form1" ;
	
	protected PageContext pageContext = null ;//页面上下文
	protected boolean bIsStop = false;
	protected Map<Integer, String> readyScriptSet = null;//onready js
	protected Map<String ,ArrayList<String>> rulesScriptSet = null;//表单规则js
	protected Map<String ,ArrayList<String>> messagesScriptSet = null;//表单 规则消息
	
	protected boolean bloadData = false;//記錄是否已經加載過數據
	protected String strPageName = "";
	protected String strBackendPageName = "";
	
	protected LinkedHashMap <String,Vector<FormItem>> formItems = null ;//頁面表單元素
	protected Hashtable<String,Vector<FormItem>> tagItems = null ;//标签表單元素
	protected boolean bBackEndMode = false;//是不是ajax模式
	protected Exception exception = null ;//後臺頁面異常
	protected Utils utils = null; //記錄utils
	protected String layout = "normal"; //normal border 頁面佈局
	protected boolean bSupportWest = false;//當layout = border 果有效
	protected boolean bSupportEast = false;
	protected boolean bSupportIframe = false;
	protected StringBuilderEx layoutConfig = null; 

	protected boolean bSpOpen = true;//搜索表單是否自動打開
	protected boolean bFilterEnab = false;//Filter按鈕是否誤用

	protected Hashtable<String,Boolean> btnDisabledConfig = null;//工具欄按鈕是否啟用配置  2012/01/30 扩展按钮的其他命令
	
	protected Vector<String> cmds = null;//頁面命令  用來在頁面結束的時候執行一些動作
	public static final String CMD_TOOLBAR_BUTTON_JS = "CMD.TOOLBAR.BUTTON.JS"; //工具欄按鍵事件
	public static final String CMD_TOOLBAR_BUTTON_FILTER_JS = "CMD.TOOLBAR.BUTTON.FILTER.JS"; //工具欄Filter按鍵事件
	protected Vector<String> autoData = new Vector<String>();//自動完成用到的數據
	protected Vector<String> multisData = new Vector<String>();//多选用到的數據
	
	protected Vector<String> gridData = new Vector<String>();//表格用到的數據
	protected boolean bDebug = false ;
	protected String strSpId = "";
	
	protected String strExportType = "";//导出类型
	protected Vector<Export> exportNodes = null;//需要导出的结点
	protected boolean bJxl = false;//是否需要导出java excel
	protected String exportFileName = "";
	
	protected Map<String,Object> listItemData = null ;//记录帶數據源的控件的數據;
	
	protected Vector<String> readonlyNodes = null;//記錄已經註冊過readonly的控件
	protected String helpURL = "";
	
	protected boolean loading = true;//loading的效果
	protected boolean bWelcome = true;//是否显示欢迎信息
	protected int minWidth = 650;//页面最小宽度
	

	protected Toolbar toolbar = null;//工具栏
	protected PageTitle pageTitle = null;//页面标题
	protected Map<String ,TableToolbar> tableToolbars = new HashMap<String ,TableToolbar>();
	protected BaseExportActionHelper exportAction = null;//导出Action
	protected ReportExportActionHelper reportAction = null;//導出報表
	
	protected boolean bFastExport = false ;//是否开启快速导出模式
	
	protected Map selectData = new HashMap();//下拉框的数据 ,用来存放option
	protected boolean bSupportExtJs = false;//是否要支持extjs
	protected boolean bSupportPrint = false;//是否要支持print js
	protected boolean bSupportTree  = false;//是否要支持tree js
	protected boolean bSupportYarnCont  = false;//是否要支持成份的js
	
	protected boolean bPrivilege = true;//是否有访问页面的权限
	protected String strPrivilegeMsg = "";//沒有權限時的附加消息
	protected boolean bformNoAction = false;//form 是否加action屬性

	

	protected boolean bPageNameDisplay = false ;
	
	protected boolean bFastMode = false;//是否开启极速模式
	protected boolean bLogJs = false;//是否调试js
	protected int uniqueid = 0;//唯一值
	protected boolean bhasDialog = false;//是否有对话框
	protected DialogTag dialog = null;//当前对话框
	protected boolean bForbiddenRighthand = true;//禁用右键
	private String jsessionid = "";
	private String nextRedirectPage = "" ;
	private String nextForwardPage = "" ;
	private boolean bPanmenuPage = true;//是否是菜單頁面
	private boolean bCustomPageJsPosition = false;
	
	public boolean isCustomPageJsPosition() {
		return bCustomPageJsPosition;
	}

	public void setCustomPageJsPosition(boolean bCustomPageJsPosition) {
		this.bCustomPageJsPosition = bCustomPageJsPosition;
	}

	public boolean isMenuPage() {
		return bPanmenuPage;
	}

	public void setMenuPage(boolean bPanmenuPage) {
		this.bPanmenuPage = bPanmenuPage;
	}

	private BaseAction baseAction = null;
	
	public BaseAction getBaseAction() {
		return baseAction;
	}

	public void setBaseAction(BaseAction baseAction) {
		this.baseAction = baseAction;
	}

	/**
	 * @return 唯一id
	 */
	public String getUniqueid(){
		this.uniqueid++;
		return "pan"+this.uniqueid;
	}
	
	/**
	 * @param key
	 * @return
	 * 取表格工具栏
	 */
	public TableToolbar getTableToolbars(String key){
		if(!tableToolbars.containsKey(key)){
			TableToolbar tabToolbar = new TableToolbar();
			tableToolbars.put(key,tabToolbar);
			return tabToolbar;
		}
		return tableToolbars.get(key);
	}
	
	
	/**
	 * @param key
	 * @return
	 * 是否已經註冊過readonly事件
	 */
	public boolean isRegisterReadonlyJs(String key){
		if(this.readonlyNodes == null)
			return false;
		return this.readonlyNodes.contains(key);
	}
	
	/**
	 * @param key
	 * 註冊readonly事件
	 */
	public void addReadonlyNode(String key){
		if(this.readonlyNodes == null)
			this.readonlyNodes = new Vector<String>();
		
		StringBuilderEx sb = new StringBuilderEx();
//		sb.Append("$P.form.enab('%1$s',false);",key);
		sb.Append("$P.form.enabitems['%1$s']=true;",key);
		this.RegisterOnReadyScript(SCRIPTRUN_ONREADY,sb.toString());
		this.readonlyNodes.add(key);
	}
	
	public boolean listItemDataContainsKey(String key){
		if(listItemData == null)
			return false;
		return listItemData.containsKey(key);
	}
	
	public Object getListItemData(String key){
		if(listItemData == null)
			return null;
		return listItemData.get(key);
	}
	
	public void addListItemData(String key,Object data){
		if(listItemData == null)
			listItemData = new HashMap<String,Object>();
		
		listItemData.put(key,data);
	}
	
	public Map<String ,BaseDataEntity> getListItemRecordMap(String name){
		if(listItemData == null)
			return null;
		return (Map<String ,BaseDataEntity>)listItemData.get(name+"_record");
	}
	
	public BaseDataEntity getListItemRecord(String name,String value){
		BaseDataEntity record = null;
		Map<String ,BaseDataEntity> map = this.getListItemRecordMap(name);
		if(map != null )record = map.get(value);
		if(record == null){
			record = new BaseDataEntity();
		}
		return record;
	}
	
	public String getListItemRecordAttributeValue(String name,String key,String value){
		return this.getListItemRecord(name,value).gpsv(key);
	}
	
	public void addListItemRecordMap(String key,Object data){
		if(listItemData == null)
			listItemData = new HashMap<String,Object>();
		
		listItemData.put(key+"_record",data);
	}
	
	/**
	 * 导出文件
	 */
	public void Export(){
		if((this.getExportNodes() == null || this.getExportNodes().size() == 0 )&& this.getExportAction().getWb1() == null)
			return ;
		this.getExportAction().Export();
	}
	
	/**
	 * 導出報表
	 * @throws Exception 
	 */
	public void ExportReport() throws Exception{
		this.getReportAction().Export();
	}
	
	public String getSpId() {
		return strSpId;
	}

	public void setSpId(String strSpId) {
		this.strSpId = strSpId;
	}

	public Vector<String> getCmds() {
		return cmds;
	}
	
	public void RegisterCmdScript(String strCmd){
		if(this.cmds == null )
			this.cmds = new Vector<String>();
		
		this.cmds.add(strCmd);
	}
	
	public Hashtable<String,Boolean> getBtnDisabledConfig(){
		if(btnDisabledConfig == null)
			btnDisabledConfig = new Hashtable<String, Boolean>();
		return btnDisabledConfig;
	}
	
	public boolean isBtnDisabled(String strBtnId){
		if(btnDisabledConfig == null)
			return true;
		
		if(btnDisabledConfig.get(strBtnId) == null )
			return true ;
		
		return btnDisabledConfig.get(strBtnId);
	}
	
	
	public void addItem(String name,FormItem formItem) {
		if(this.formItems == null )
			this.formItems = new LinkedHashMap<String,Vector<FormItem>>();
		
		Vector<FormItem> vector = null;
		if(this.formItems.containsKey(name)){
			vector = this.formItems.get(name);
		}else{
			vector = new Vector<FormItem>();
		}
		vector.add(formItem);
		this.formItems.put(name, vector);
	}
	
	public LinkedHashMap<String,Vector<FormItem>> getItems(){
		return this.formItems;
	}
	
	public int getItemSize(String name){
		return getItemSize(name,false);
	}
	
	public int getItemSize(String name ,boolean ignoreRaido){
		if(this.getItems() == null)
			return 0;
		
		if(!this.getItems().containsKey(name))
			return 0 ;
		
		int size = this.getItems().get(name).size();
		if(ignoreRaido && size > 1 ){
			FormItem object = this.getItems().get(name).get(0);
			
			if(object instanceof Input){
				if("radio".equalsIgnoreCase(((Input)object).getType())){
					size = 1;
				}
			}
		}
		return size;
	}
	
	
	public void addTagItem(String name,FormItem formItem) {
		if(this.tagItems == null )
			this.tagItems = new Hashtable<String,Vector<FormItem>>();
		
		Vector<FormItem> vector = null;
		if(this.tagItems.containsKey(name)){
			vector = this.tagItems.get(name);
		}else{
			vector = new Vector<FormItem>();
		}
		vector.add(formItem);
		this.tagItems.put(name, vector);
	}
	
	public Hashtable<String,Vector<FormItem>> getTagItems(){
		return this.tagItems;
	}
	
	public int getTagItemSize(String name){
		return getTagItemSize(name,false);
	}
	
	public int getTagItemSize(String name ,boolean ignoreRaido){
		if(this.getTagItems() == null)
			return 0;
		
		if(!this.getTagItems().containsKey(name))
			return 0 ;
		
		int size = this.getTagItems().get(name).size();
		if(ignoreRaido && size > 1 ){
			FormItem object = this.getTagItems().get(name).get(0);
			
			if(object instanceof Input){
				if("radio".equalsIgnoreCase(((Input)object).getType())){
					size = 1;
				}
			}
		}
		return size;
	}
	
	
	/**
	 * @param pageContext
	 * 初始化页面
	 */
	public void Init(PageContext pageContext)throws Exception{
		this.setInit(true);
		if(!this.isAlreadyLoadData()){
			if(this.pageContext == null)
				PreparePageEnv(pageContext);
			
			//转发要逻辑处理页面
			forwardActionPage();
		}
	}
	
	/**
	 * @param pageContext
	 * 初始化页环境
	 */
	public void PreparePageEnv(PageContext pageContext){
		this.pageContext = pageContext;
		this.pageContext.getRequest().setAttribute(TAG_CURRENT_PAGE,this);
		if(this.pageContext.getRequest().getAttribute(TAG_CURRENT_UTILS) == null) {
			this.utils = new Utils(this.pageContext.getRequest()); 
		}else{
			this.utils = (Utils)this.pageContext.getRequest().getAttribute(TAG_CURRENT_UTILS);
		}
		this.jsessionid = this.getRequest().getSession().getId();
		
		if(!this.IsBackEndMode()){
			//处理页面信息
			try{
				String strURI = this.getRequest().getRequestURI();
				this.setPageName(strURI.substring(strURI.lastIndexOf("/")+1, strURI.length()));
				this.setBackendPageName(StringHelper.Format("%1$s_backend.jsp",this.getPageName().substring(0,this.getPageName().indexOf("."))));
			}catch (Exception e) {
				e.printStackTrace();
				log.debug(StringHelper.Format("页面%1$s 后台处理页面设置错误:%2$s",this.getRequest().getRequestURI(),e.getMessage()));
			}
			
			if(this.toolbar == null)
				this.toolbar = new Toolbar();
			if(this.pageTitle == null)
				this.pageTitle = new PageTitle();
		}
	}
	
	public boolean forwardUIPage() throws Exception{
		this.setLoadData(true);
		if(!StringHelper.IsNullOrEmpty(getPageName())){
			try {
				this.getRequest().setCharacterEncoding("UTF-8");
				if(this.getRedirectPage().length() >0){
					this.getResponse().sendRedirect(this.getContextPath()+this.getRedirectPage());
				}else if(this.getForwardPage().length() > 0){
					this.getUtils().getForm().resetAction();//表單對象動作清空
					this.getRequest().removeAttribute(TAG_CURRENT_PAGE);//清空頁面對象
					//this.getRequest().removeAttribute(TAG_CURRENT_UTILS);
					
					this.getRequest().getRequestDispatcher(this.getForwardPage()).forward(this.getRequest(), this.getResponse());
				}else if(this.isPrivilege()){
					if("export".equals(this.getUtils().getForm().getAction())){
						this.getRequest().getRequestDispatcher(getPageName()+";jsessionid="+this.jsessionid).forward(this.getRequest(), this.getResponse());
					}else{
						this.getRequest().getRequestDispatcher(getPageName()).forward(this.getRequest(), this.getResponse());
					}
				}else{
					String temParams = "";
					if(!StringHelper.IsNullOrEmpty(this.getPrivilegeMsg())){
						temParams += "?msg="+utils.unescape(this.getPrivilegeMsg());
					}
					this.getResponse().sendRedirect(this.getContextPath()+TAG_ACCESSDENY_PAGE+temParams);
				}
				return true;
			} catch (Exception e) {
				e.printStackTrace();
				this.setLoadData(false);
				throw e;
			}
		}
		return false;
	}
		
	public boolean forwardActionPage() throws Exception{
		if(!StringHelper.IsNullOrEmpty(getBackendPageName())){
			try {
				this.getRequest().setCharacterEncoding("UTF-8");
				if(this.isPrivilege())
					if("export".equals(this.getUtils().getForm().getAction())){
						this.getRequest().getRequestDispatcher(getBackendPageName()+";jsessionid="+this.jsessionid).forward(this.getRequest(), this.getResponse());
					}else{
						this.getRequest().getRequestDispatcher(getBackendPageName()).forward(this.getRequest(), this.getResponse());
					}
				else{
					String temParams = "";
					if(!StringHelper.IsNullOrEmpty(this.getPrivilegeMsg())){
						temParams += "?msg="+utils.unescape(this.getPrivilegeMsg());
					}
					this.getResponse().sendRedirect(this.getContextPath()+TAG_ACCESSDENY_PAGE+temParams);
				}
				this.setFinshed(true);
				return true;
			} catch (Exception e) {
				e.printStackTrace();
				this.setFinshed(false);
				throw e;
			}
		}
		return false;
	}
	
	/**
	 * 加载页面
	 */
	final public void Load()
	{
		OnLoad();
	}
	
	/**
	 * 在加载页面时触发
	 */
	protected void OnLoad()
	{
		StringBuilderEx sb = new StringBuilderEx();
		if(this.isExport()){
			//导出excel
			if(StringHelper.Compare("xls",this.getExportType(),true) == 0){
				this.getResponse().setContentType("application/vnd.ms-excel;charset=UTF-8");
				this.getResponse().addHeader("Content-Disposition", "filename=test.xls");
			}
			
			ReturnData ret = utils.getReturnData();
			if(ret.isError()){
				try {
					this.setStop(true);
					sb.Reset();
					sb.Append("<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\">\r\n");
					sb.Append("<html>\r\n<meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\">\r\n<head></head>\r\n<body>\r\n");
					sb.Append(ret.getCallResult().getErrorInfo());
					sb.Append("\r\n</body></html>");
					this.getResponse().getWriter().write(sb.toString());
					this.getResponse().getWriter().close();
				} catch (IOException e) {
					e.printStackTrace();
					e.printStackTrace();
				}
			}
		}
		
		
		sb.Reset();
		//禁用右键
		if(this.isForbiddenRighthand() && !"127.0.0.1".equals(this.getRequest().getRemoteAddr())){
			sb.Append("document.oncontextmenu=function(){return false;};");
		}
		
		//註冊getContextPath
		sb.Append("$P.cp=\"%1$s\";",this.getContextPath());
		sb.Append("$P.jsessionid=\"%1$s\";",this.getRequest().getSession().getId());
		
		
		//註冊公用的消息
		sb.Append("$P.msg['eperror']=\"%1$s\";",this.getUtils().i18n("請先執行查詢,然後再導出資料!"));
		sb.Append("$P.msg['epnodataerror']=\"%1$s\";",this.getUtils().i18n("可能沒有資料,確定要導出?"));
		sb.Append("$P.msg['confirm']=\"%1$s\";",this.getUtils().i18n("確認執行[{0}]操作嗎?"));
		//註冊layout
		sb.Append("$P.form.formid = '%1$s';",this.getDefaultFormID());
		sb.Append("$P.setLayout('%1$s');",StringHelper.getValue(this.getLayout(), "normal"));
		this.RegisterOnReadyScript(SCRIPTRUN_REALTIME, sb.toString());
		
		if(this.isBorderLayout()){
			this.setFastMode(true);
		}
		//是否是快速模式
		if(this.isFastMode())
			this.RegisterOnReadyScript(SCRIPTRUN_REALTIME, "$P.fast = true;");
		
		if(this.isSupportPrint()){
			this.RegisterOnReadyScript(SCRIPTRUN_REALTIME, "$P.print = true;");
		}
		
		this.getBtnDisabledConfig().put("help", false);
		this.getBtnDisabledConfig().put("export", false);
		this.getBtnDisabledConfig().put("print", false);
		
		//处理表格的JS(停用,放到tablebuilder中處理)
		//this.RegisterOnReadyScript(SCRIPTRUN_TABS, PageJsGear.getTableJs(this));
		
		//注册页面初始布局
		PageJsGear.registerPageLayoutJs(this);
		
		//设置js语言
		
		
		String language = (String)this.getRequest().getSession().getAttribute("languagecode");
		if("vn".equalsIgnoreCase(language) || "zh-ca".equalsIgnoreCase(language)){
			sb.Reset();
			sb.Append("$P.setLang('vn');");
		}else if("zh-tw".equalsIgnoreCase(language)){
			sb.Reset();
			sb.Append("$.validator.messages['custom']=\"%1$s\";","請修復這個欄位.");
			sb.Append("$.validator.messages['required']=\"%1$s\";","此欄位不可以為空.");
			sb.Append("$.validator.messages['remote']=\"%1$s\";","請修復這個欄位.");
			sb.Append("$.validator.messages['email']=\"%1$s\";","請輸入有效的郵件地址.");
			sb.Append("$.validator.messages['number']=\"%1$s\";","請輸入有效的數字.");
			sb.Append("$.validator.messages['digits']=\"%1$s\";","必须输入整数.");
			sb.Append("$.validator.messages['maxlength']=\"%1$s\";","請輸入小行等於{0}個字符.");
			sb.Append("$.validator.messages['minlength']=\"%1$s\";","請至少輸入{0}個字符.");
			sb.Append("$.validator.messages['rangelength']=\"%1$s\";","請輸入{0}-{1}個字字符.");
			sb.Append("$.validator.messages['range']=\"%1$s\";","請輸入{0}-{1}範圍內的值.");
			sb.Append("$.validator.messages['max']=\"%1$s\";","請輸入小於等於{0}的值.");
			sb.Append("$.validator.messages['min']=\"%1$s\";","請轉入大於等於{0}的值.");
		}else if("vn".equalsIgnoreCase(language)){
			
		}
		this.RegisterOnReadyScript(SCRIPTRUN_ONREADY,sb.toString());
		
		//表單事件
		this.RegisterOnReadyScript(SCRIPTRUN_ONREADY, PageJsGear.getFormSubmitJs(this));
		
		//註冊窗口改變大小事件
		if(!this.isFastMode()){
			sb.Reset();
			sb.Append(" try{");
				sb.Append(" if($(window.frameElement).length >0){");
					sb.Append(" $(window.frameElement).resize(function(){$P.refresh();});");
					sb.Append(" $(window).resize(function(){$P.refresh();});");
				sb.Append(" }else{");
					sb.Append(" $(window).resize(function(){$P.refresh();});");
				sb.Append(" }");
			sb.Append(" }catch(e){");
				sb.Append(" $(window).resize(function(){$P.refresh();}");
			sb.Append(" );}");
			this.RegisterOnReadyScript(SCRIPTRUN_ONREADY, sb.toString());
		}
		
//		刷新布局
		this.RegisterOnReadyScript(SCRIPTRUN_LAST, "$P.refresh();");
		
//		關閉loading
		this.RegisterOnReadyScript(SCRIPTRUN_LAST, "if($P.loading != null) $P.loading.hide();");
	}
	
	
	
	/**
	 * @param pageContext
	 * 初始化页面
	 */
	public void InitBackEnd(PageContext pageContext){
		this.setInit(true);
		PreparePageEnv(pageContext);
	}
	
	/**
	 * @param pageContext
	 * 初始化页面
	 */
	public void LoadBackEnd(){
		
	}
	
	/**
	 * 获取网页流输出对象
	 * @return
	 */
	public JspWriter getWriter()
    {
        return pageContext.getOut();
    }
	
	/**
     * 输出页面内容
     * @param strOutput
     */
     public void Output(String strOutput)
    {
    	try
    	{
    		this.getWriter().write(strOutput);
    	}
    	catch(Exception ex)
    	{
    		ex.printStackTrace();
    		log.error("页面输出出现错误", ex);
    	}
    }
	
	/**
     * 判断页面是否停止处理
     * @return
     */
    public boolean IsStop()
    {
    	return  bIsStop ;
    }
    
    public boolean setStop(boolean bStop)
    {
    	return  this.bIsStop = bStop;
    }
	
	public HttpServletRequest getRequest(){
		return (HttpServletRequest)pageContext.getRequest();
	}
	
	public HttpServletResponse getResponse(){
		return (HttpServletResponse)pageContext.getResponse();
	}
	
	public PageContext getPageContext() {
		return pageContext;
	}
	
	
	public Map<Integer, String> getReadyScriptSet(){
		return this.readyScriptSet;
	}
	 /**
     * 注册文档加载完毕时执行的代码
     * @param nLevel
     * @param strScript
     */
    final public void RegisterOnReadyScript(int nLevel,String strScript)
    {
    	if(StringHelper.IsNullOrEmpty(strScript)){
    		return;
    	}
    	
    	if(nLevel <SCRIPTRUN_REALTIME || nLevel>SCRIPTRUN_LAST)
    		return;
    	
    	if(readyScriptSet == null)
    	{
    		readyScriptSet = new TreeMap<Integer, String>() ;
    	}
    	
    	String strLastScript = "";
    	if(readyScriptSet.containsKey(nLevel))
    		strLastScript  = readyScriptSet.get(nLevel);

    	if(StringHelper.Length(strLastScript)>0 && nLevel != SCRIPTRUN_GRIDDATA)
    	{
    		strLastScript += "\r\n";
    	}
    	
    	if(scriptNeedIf(nLevel))
    		strLastScript += StringHelper.Format("if(1){\r\n %1$s \r\n}",strScript);
    	else if(nLevel == SCRIPTRUN_GRIDDATA)
    		strLastScript += StringHelper.Format(" %1$s ",strScript);
    	else
    		strLastScript += StringHelper.Format("\r\n %1$s \r\n",strScript);
    	
    	readyScriptSet.put(nLevel, strLastScript);
    }
    
    final public boolean scriptNeedIf(int lev){
    	if(lev == SCRIPTRUN_REALTIME || lev == SCRIPTRUN_HTML || lev == SCRIPTRUN_GRIDDATA)
    		return false ;
    	else 
    		return true;
    }
    
    
    final public void RegisterRulesScript(String strScript){
    	if(StringHelper.IsNullOrEmpty(strScript)) return ;
    	
    	RegisterRulesScript(this.getDefaultFormID(), strScript);
    }
    
    final public void RegisterRulesScript(String formId,String strScript){
    	if(StringHelper.IsNullOrEmpty(strScript)) return ;
    	if(rulesScriptSet == null)
    	{
    		rulesScriptSet = new HashMap<String ,ArrayList<String>>();
    	}
    	
    	if(!StringHelper.IsNullOrEmpty(strScript))
    	{
    		ArrayList<String> list = rulesScriptSet.get(formId) ;
    		if(list == null)
    		{
    			 list = new ArrayList<String>();
    		}else
    		{
    			list.add(",");
    		}
    		list.add(strScript);
    		rulesScriptSet.put(formId, list);
    	}
    }
    
    public String outRulesScript(){
    	return outRulesScript(this.getDefaultFormID());
    }

    public String outRulesScript(String formId){
    	if(rulesScriptSet == null)
    		return "" ;
    	
    	ArrayList<String> list = rulesScriptSet.get(formId) ;
    	if(list == null)
    		return "" ;
    	
    	StringBuilderEx sb = new StringBuilderEx();
    	for(int i=0; i<list.size(); i++){
    		String script = list.get(i);
    		if(i == 0)
    			sb.Append(",\r\n	rules:{");
    		
    		sb.Append(script);
    		
    		if(i == (list.size() -1))
    			sb.Append("\r\n		}");
    	}
    	return sb.toString();
    }
    
    final public void RegisterMessagesScript(String strScript){
    	if(StringHelper.IsNullOrEmpty(strScript)) return ;
    	
    	RegisterMessagesScript(this.getDefaultFormID(), strScript);
    }
    
    final public void RegisterMessagesScript(String formId,String strScript){
    	if(StringHelper.IsNullOrEmpty(strScript)) return ;
    	
    	if(messagesScriptSet == null)
    	{
    		messagesScriptSet = new HashMap<String ,ArrayList<String>>();
    	}
    	
    	if(!StringHelper.IsNullOrEmpty(strScript))
    	{
    		ArrayList<String> list = messagesScriptSet.get(formId) ;
    		if(list == null)
    		{
    			 list = new ArrayList<String>();
    		}else
    		{
    			list.add(",");
    		}
    		list.add(strScript);
    		messagesScriptSet.put(formId, list);
    	}
    }
    
    public String outMessagesScript(){
    	return outMessagesScript(this.getDefaultFormID());
    }

    public String outMessagesScript(String formId){
    	if(messagesScriptSet == null)
    		return "" ;
    	
    	ArrayList<String> list = messagesScriptSet.get(formId) ;
    	if(list == null)
    		return "" ;
    	
    	StringBuilderEx sb = new StringBuilderEx();
    	for(int i=0; i<list.size(); i++){
    		String script = list.get(i);
    		if(i == 0)
    			sb.Append(",\r\n	messages:{");
    		
    		sb.Append(script);
    		
    		if(i == (list.size() -1))
    			sb.Append("\r\n		}");
    	}
    	return sb.toString();
    }
    
    
    
    public String getDefaultFormID() {
		return strDefaultFormID;
	}
    
    public String getDefaultFormValidatorID() {
    	return StringHelper.Format("%1$sValidator",this.getDefaultFormID());
	}

	public void setDefaultFormID(String strDefaultFormID) {
		this.strDefaultFormID = strDefaultFormID;
	}
	
	/**
	 * @return
	 * 輸出頁面隱藏欄位
	 */
	public String outputHiddenItem(){
		if(this.isExport()) return "";
		JMForm form = utils.getForm();
		StringBuilderEx sb = new StringBuilderEx();
		sb.Append("\r\n<input type=\"hidden\" id=\"actiontext\" name=\"actiontext\" value=\"\" />");//记录中文
		sb.Append("\r\n<input type=\"hidden\" id=\"actiontemp\" name=\"actiontemp\" value=\"\" />");//是否是自定义验证
		sb.Append("\r\n<input type=\"hidden\" id=\"actionvaluetemp\" name=\"actionvaluetemp\" value=\"\" />");//是否是自定义验证
		sb.Append("\r\n<input type=\"hidden\" id=\"action\" name=\"action\" value=\"\" />");
		sb.Append("\r\n<input type=\"hidden\" id=\"actionvalue\" name=\"actionvalue\" value=\"\" />");
		
		sb.Append("\r\n<input type=\"hidden\" id=\"backpage\" name=\"backpage\" value=\"%1$s\" />",this.getBackendPageName());
		sb.Append("\r\n<input type=\"hidden\" id=\"%1$s\" name=\"%1$s\" value=\"%2$s\" />",Token.TOKEN_STRING_NAME,Token.getTokenString(this.getRequest().getSession()));
		sb.Append("\r\n<input type=\"hidden\" id=\"panmenusn\" name=\"panmenusn\" value=\"%1$s\" />",StringHelper.getValue(this.getRequest().getParameter("panmenusn")));
		
		
		sb.Append("\r\n<input type=\"hidden\" id=\"oldaction\" name=\"oldaction\" value=\"%1$s\" />",
				this.isExport() ? form.gpsv("oldaction") : form.gpsv("action"));
		sb.Append("\r\n<input type=\"hidden\" id=\"oldactionvalue\" name=\"oldactionvalue\" value=\"%1$s\" />",
				this.isExport() ? form.gpsv("oldactionvalue") : form.gpsv("actionvalue"));
		//sb.Append("\r\n<input type=\"hidden\" id=\"_page\" name=\"_page\" value=\"%1$s\" />",form.gpsv("_page").replace("-1",""));//分頁 -1不需要显示
		return sb.toString();
	}
	
	public ReturnData getReturnData(){
		if(this.utils == null) return null;
		return this.utils.getReturnData();
	}
	
	public String getPageName() {
		return strPageName;
	}

	public void setPageName(String strPageName) {
		this.strPageName = strPageName;
	}

	public String getBackendPageName() {
		return strBackendPageName;
	}

	public void setBackendPageName(String strBackendPageName) {
		this.strBackendPageName = strBackendPageName;
	}
	
	public boolean isAlreadyLoadData() {
		return this.bloadData;
	}

	public void setLoadData(boolean bloadData) {
		this.bloadData = bloadData;
	}
	
	/**
	 * 判断是否为后台执行模式
	 * @return
	 */
	public boolean IsBackEndMode()
	{
		return bBackEndMode;
	}
	
	public void setBackEndMode(boolean bBackEndMode)
	{
		this.bBackEndMode = bBackEndMode;
	}
	
	public Utils getUtils() {
		return utils;
	}

	public void setUtils(Utils utils) {
		this.utils = utils;
	}

	public Exception getException() {
		return exception;
	}

	public void setException(Exception exception) {
		this.exception = exception;
	}
	public boolean isFinshed() {
		return bFinshed;
	}

	public void setFinshed(boolean bFinshed) {
		this.bFinshed = bFinshed;
	}
	
	public String getLayout() {
		return layout;
	}

	public void setLayout(String layout) {
		this.layout = layout;
	}
	
	public boolean isNormalLayout(){
		return TAG_LAYOUT_NORMAL.equalsIgnoreCase(this.getLayout());
	}
	
	public boolean isBorderLayout(){
		return TAG_LAYOUT_BORDER.equalsIgnoreCase(this.getLayout());
	}
	
	public boolean isSpOpen() {
		return bSpOpen;
	}

	public void setSpOpen(boolean bSpOpen) {
		this.bSpOpen = bSpOpen;
	}
	
	public boolean isFilterEnab() {
		return bFilterEnab;
	}

	public void setFilterEnab(boolean bFilterEnab) {
		this.bFilterEnab = bFilterEnab;
	}
	
	/**
	 * @param name
	 */
	public void addAutoData(String name){
		this.autoData.add(name);
		
	}
	
	/**
	 * @param key
	 * @return
	 */
	public boolean autoDatacontainsKey(String key){
		return this.autoData.contains(key);
	}
	
	/**
	 * @param name
	 */
	public void addMultisData(String name){
		this.multisData.add(name);
		
	}
	
	/**
	 * @param key
	 * @return
	 */
	public boolean multisDatacontainsKey(String key){
		return this.multisData.contains(key);
	}
	
	
	
	/**
	 * @param name
	 */
	public void addGridData(String name){
		this.gridData.add(name);
		
	}
	
	/**
	 * @param key
	 * @return
	 */
	public boolean gridDatacontainsKey(String key){
		return this.gridData.contains(key);
	}

	public boolean isDebug() {
		return bDebug;
	}

	public void setDebug(boolean debug) {
		bDebug = debug;
	}

	public String getExportType() {
		return strExportType;
	}

	public void setExportType(String strExportType) {
		this.strExportType = strExportType;
	}
	
	/**
	 * @return
	 * 是否是导出模板
	 */
	public boolean isExport(){
		return !StringHelper.IsNullOrEmpty(this.getExportType());
	}
	
	/**
	 * @return
	 */
	public boolean isExportFile(){
		if("xls".equals(this.getExportType())){
			return this.isJxl();
		}
		
		return this.isExport();
	}
	
	public Vector<Export> getExportNodes() {
		return exportNodes;
	}

	public void setExportNodes(Vector<Export> exportNodes) {
		this.exportNodes = exportNodes;
	}
	
	public void addExportNode(Export node) {
		if(node == null || node.getItems() == null || node.getItems().size() == 0)
			return ;
		if(this.exportNodes == null)
			this.exportNodes = new Vector<Export>();
		
		this.exportNodes.add(node);
	}

	public boolean isJxl() {
		return bJxl;
	}

	public void setJxl(boolean jxl) {
		bJxl = jxl;
	}

	public String getExportFileName() {
		if(StringHelper.IsNullOrEmpty(exportFileName))
			return this.getPageName().replace(".jsp","");
		return exportFileName;
	}

	public void setExportFileName(String exportFileName) {
		this.exportFileName = exportFileName;
	}

	public String getHelpURL() {
		return helpURL;
	}

	public void setHelpURL(String helpURL) {
		this.helpURL = helpURL;
		
		//注册help urljs
		if(!StringHelper.IsNullOrEmpty(helpURL)){
			try {
				this.RegisterOnReadyScript(SCRIPTRUN_ONREADY,StringHelper.Format("$P.helpurl=\""+this.getContextPath()+"/%1$s/%2$s\";","系統使用說明",helpURL));
			} catch (Exception e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
	}
	
	public String getContextPath(){
		return this.getRequest().getContextPath();
	}
	
	public String getServerPath(){
		return this.getRequest().getScheme() +"://"+this.getRequest().getServerName()+this.getRequest().getContextPath();
	} 
	
	public boolean isLoading() {
		return loading;
	}

	public void setLoading(boolean loading) {
		this.loading = loading;
	}

	public Toolbar getToolbar() {
		return toolbar;
	}

	public void setToolbar(Toolbar toolbar) {
		this.toolbar = toolbar;
	}

	public PageTitle getPageTitle() {
		return pageTitle;
	}

	public void setPageTitle(PageTitle pageTitle) {
		this.pageTitle = pageTitle;
	}

	public boolean hasInit() {
		return bInit;
	}

	public void setInit(boolean init) {
		bInit = init;
	}


	public boolean isWelcome() {
		return bWelcome;
	}


	public void setWelcome(boolean welcome) {
		bWelcome = welcome;
	}


	public int getMinWidth() {
		return minWidth;
	}


	public void setMinWidth(int minWidth) {
		this.minWidth = minWidth;
		
		//注册页面最小宽度
		if(this.getMinWidth() != 650){
			this.RegisterOnReadyScript(SCRIPTRUN_ONREADY,StringHelper.Format("$P.minWidth = %1$s;",this.getMinWidth()));
		}
	}


	public BaseExportActionHelper getExportAction() {
		if(exportAction == null){
			exportAction = new BaseExportActionHelper();
			exportAction.init(this);
		}
		return exportAction;
	}
	
	public ReportExportActionHelper getReportAction() {
		if(reportAction == null){
			reportAction = new ReportExportActionHelper();
			reportAction.init(this);
		}
		return reportAction;
	}
	
	public void setExportAction(BaseExportActionHelper exportAction) {
		this.exportAction = exportAction;
	}


	public boolean isFastExport() {
		return bFastExport;
	}


	public void setFastExport(boolean fastExport) {
		bFastExport = fastExport;
	}


	public Map getSelectData() {
		return selectData;
	}


	public boolean isSupportExtJs() {
		return bSupportExtJs;
	}


	public void setSupportExtJs(boolean supportExtJs) {
		bSupportExtJs = supportExtJs;
	}


	public boolean isPrivilege() {
		return bPrivilege;
	}


	public void setPrivilege(boolean privilege) {
		bPrivilege = privilege;
	}


	public boolean isPageNameDisplay() {
		return bPageNameDisplay;
	}


	public void setPageNameDisplay(boolean pageNameDisplay) {
		bPageNameDisplay = pageNameDisplay;
	}


	public boolean isFastMode() {
		return bFastMode;
	}


	public void setFastMode(boolean fastMode) {
		bFastMode = fastMode;
	}


	public boolean isSupportPrint() {
		return bSupportPrint;
	}


	public void setSupportPrint(boolean supportPrint) {
		bSupportPrint = supportPrint;
	}


	public boolean isLogJs() {
		return bLogJs;
	}


	public void setLogJs(boolean logJs) {
		bLogJs = logJs;
	}
	
	public boolean hasDialog() {
		return bhasDialog;
	}

	public void sethasDialog(boolean bhasDialog) {
		this.bhasDialog = bhasDialog;
	}
	
	public DialogTag getDialog() {
		return dialog;
	}

	public void setDialog(DialogTag dialog) {
		this.sethasDialog(true);
		this.dialog = dialog;
	}
	
	public boolean isForbiddenRighthand() {
		return bForbiddenRighthand;
	}

	public void setForbiddenRighthand(boolean bForbiddenRighthand) {
		this.bForbiddenRighthand = bForbiddenRighthand;
	}
	
	public String getRedirectPage() {
		return nextRedirectPage;
	}

	public void setRedirectPage(String nextRedirectPage) {
		this.nextRedirectPage = nextRedirectPage;
	}
	
	public String getForwardPage() {
		return nextForwardPage;
	}

	public void setForwardPage(String nextForwardPage) {
		this.nextForwardPage = nextForwardPage;
	}
	
	public boolean isSupportEast() {
		return bSupportEast;
	}

	public void setSupportEast(boolean bSupportEast) {
		this.bSupportEast = bSupportEast;
	}

	public boolean isSupportWest() {
		return bSupportWest;
	}
	
	public boolean isSupportIframe() {
		return bSupportIframe;
	}

	public void setSupportIframe(boolean bSupportIframe) {
		this.bSupportIframe = bSupportIframe;
	}

	public void setSupportWest(boolean bSupportWest) {
		this.bSupportWest = bSupportWest;
	}
	
	public boolean isSupportTree() {
		return bSupportTree;
	}

	public void setSupportTree(boolean bSupportTree) {
		this.bSupportTree = bSupportTree;
	}
	public String getPrivilegeMsg() {
		return strPrivilegeMsg;
	}

	public void setPrivilegeMsg(String strPrivilegeMsg) {
		this.strPrivilegeMsg = strPrivilegeMsg;
	}
	
	public boolean isSupportYarnCont() {
		return bSupportYarnCont;
	}

	public void setSupportYarnCont(boolean bSupportYarnCont) {
		this.bSupportYarnCont = bSupportYarnCont;
	}
	
	public StringBuilderEx getLayoutConfig(){
		if(layoutConfig == null){
			layoutConfig = new StringBuilderEx();
	//		layoutConfig.Append("\r\n	north__paneSelector:\"#north\",");
	//		if(page.isSupportWest())
	//			layoutConfig.Append("\r\n	west__paneSelector:\"#west\",");
	//		layoutConfig.Append("\r\n	center__paneSelector:\"#center\",");
	//		if(page.isSupportEast())
	//			layoutConfig.Append("\r\n	east__paneSelector:\"#east\",");
	//		layoutConfig.Append("\r\n	south__paneSelector:\"#south\",");
				
			layoutConfig.Append("\r\n	north__spacing_open:0");
			layoutConfig.Append("\r\n	,north__spacing_close:0");
			layoutConfig.Append("\r\n	,north__resizable:false");
			layoutConfig.Append("\r\n	,north__closable:false");
			layoutConfig.Append("\r\n	,north__fxName:'none'");
			layoutConfig.Append("\r\n	,north__size:'auto'");
	//		layoutConfig.Append("\r\n	north__togglerLength_closed:-1,");
	//		layoutConfig.Append("\r\n	north__togglerLength_open:-1,");
	//		layoutConfig.Append("\r\n north__onclose_end:$P.refresh,");
	//		layoutConfig.Append("\r\n north__onopen_end:$P.refresh,");
			
			if(this.isSupportIframe()){
				layoutConfig.Append("\r\n ,maskContents:true");
			}
			
	//		layoutConfig.Append("\r\n	fxName:'slide',");
	//		layoutConfig.Append("\r\n	fxSpeed_open:1000,");
	//		layoutConfig.Append("\r\n	fxSpeed_close:2500,");
	//		layoutConfig.Append("\r\n	fxSettings_open:{ easing: 'easeInQuint' },");
	//		layoutConfig.Append("\r\n	fxSettings_close:{ easing: 'easeOutQuint' },");
			
	//		layoutConfig.Append("\r\n	south__spacing_open:2,");
	//		layoutConfig.Append("\r\n	south__spacing_close:2,");
	//		layoutConfig.Append("\r\n	south__resizable:false,");
	//		layoutConfig.Append("\r\n	south__closable:false,");
	//		layoutConfig.Append("\r\n	resizeWhileDragging:true");
			
	//		layoutConfig.Append("\r\n	useStateCookie:false");
		}
		return layoutConfig;
	}
	
	public boolean isformNoAction() {
		return bformNoAction;
	}

	public void setformNoAction(boolean bformNoAction) {
		this.bformNoAction = bformNoAction;
	}
	/*****************流程中使用************************/
	
	/**
	 * @return
	 * 是否是簽核頁面
	 */
	public boolean isWFCheckPage(){
		return this instanceof WFPage && !this.getUtils().getForm().isNullOrEmpty("wfopstepid");
	}
	
	/**
	 * @return
	 * 是否是送簽頁面
	 */
	public boolean isWFStartPage(){
		return this instanceof WFPage && this.getUtils().getForm().isNullOrEmpty("wfopstepid");
	}
	
	public boolean hasWFInstance(){
		return !this.getUtils().getForm().isNullOrEmpty("wfinstance");
	}
	
	/**
	 * 當前流程
	 */
	WorkFlow curWF = null; 
	/**
	 * 當前流程步驟
	 */
	WFStep curWFStep = null;
	/**
	 * 當前流程實例
	 */
	WFInstance curWFInstance = null;
	/**
	 * 當前流程操作步驟
	 */
	WFOpStep curWFOpStep = null;
	/**
	 * 當前單據實體
	 */
	CrudDataEntity curData = null;
	
	public CrudDataEntity getCurData() {
		return curData;
	}

	public void setCurData(CrudDataEntity curData) {
		this.curData = curData;
	}

	public WorkFlow getCurWF() {
		return curWF;
	}

	public void setCurWF(WorkFlow curWF) {
		this.curWF = curWF;
	}
	
	public WFInstance getCurWFInstance() {
		return curWFInstance;
	}

	public void setCurWFInstance(WFInstance curWFInstance) {
		this.curWFInstance = curWFInstance;
	}

	public WFOpStep getCurWFOpStep() {
		return curWFOpStep;
	}

	public void setCurWFOpStep(WFOpStep curWFOpStep) {
		this.curWFOpStep = curWFOpStep;
	}

	public WFStep getCurWFStep() {
		return curWFStep;
	}

	public void setCurWFStep(WFStep curWFStep) {
		this.curWFStep = curWFStep;
	}
	
	/*****************流程中使用************************/
}
